﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Windows.Data;
using Foundation;
using Foundation.Spell;
using Poet.Modules;

namespace Poet.ViewModels
{
    [DataContract]
    internal class RhymerViewModel : ViewModel
    {
        private readonly EventWaitHandle _canRefresh = new ManualResetEvent(true);
        private static readonly List<SpellManager> SpellManagers = new List<SpellManager>();
        private static readonly List<CompletionManager> CompletionManagers = new List<CompletionManager>();
        private static readonly Dictionary<string, WordData> Dictionary = new Dictionary<string, WordData>(); 

        public RhymerViewModel()
        {
            Initialize();
        }

        public ObservableCollection<string> AllWords { get; private set; }
        public ObservableCollection<WordData> Words { get; private set; }

        [DataMember]
        public string Word
        {
            get { return Get(() => Word); }
            set { Set(() => Word, value); }
        }

        private ICollectionView WordsDefaultView { get; set; }

        [OnDeserialized]
        private void Initialize(StreamingContext context = default(StreamingContext))
        {
            AllWords = new ObservableCollection<string>();
            SpellManagers.AddRange(SpellColorizer.SpellCheckers);
            CompletionManagers.Add(DocumentViewModel.CompletionManager);
            SpellManagers.ForEach(m => m.Dictionary.Keys.ToList().ForEach(w => AllWords.Add(w)));
            CompletionManagers.ForEach(m => m.Dictionary.Keys.ToList().ForEach(w => AllWords.Add(w)));

            Words = new ObservableCollection<WordData>(AllWords.Select(GetWordData));
            WordsDefaultView = CollectionViewSource.GetDefaultView(Words);
            WordsDefaultView.Filter = o =>
                {
                    if (Word == null) return true;
                    var wordInfo = o as WordData;
                    if (wordInfo == null) return false;
                    return wordInfo.Word.Contains(Word);
                };

            this[() => Word].PropertyChanged += (sender, args) => WordsDefaultView.Refresh();
        }

        private static WordData GetWordData(string word)
        {
            var wordData = Dictionary.ContainsKey(word) ? Dictionary[word] : new WordData(word);
            foreach (var manager in CompletionManagers.Where(m => m.Dictionary.ContainsKey(word)))
            {
                wordData.UsingLevel = manager.Dictionary[word].GlobalUsings;
            }

            foreach (var manager in SpellManagers.Where(m => m.Dictionary.ContainsKey(word)))
            {
                wordData.RightLevel = manager.Dictionary[word] == null ? 1 : -1;
            }

            return wordData;
        }
    }

    class WordData
    {
        public WordData(string word)
        {
            Word = word;
        }

        public string Word { get; private set; }
        public int RightLevel { get; set; }    
        public int UsingLevel { get; set; }
        public int RhumLevel { get; set; }
    }
}
